{
  "nbformat": 4,
  "nbformat_minor": 0,
  "metadata": {
    "colab": {
      "name": "0427.ipynb",
      "provenance": [],
      "include_colab_link": true
    },
    "kernelspec": {
      "name": "python3",
      "display_name": "Python 3"
    },
    "accelerator": "GPU"
  },
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "view-in-github",
        "colab_type": "text"
      },
      "source": [
        "<a href=\"https://colab.research.google.com/github/yananma/5_programs_per_day/blob/master/0427.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "lJD0DWFmMbhM",
        "colab_type": "text"
      },
      "source": [
        "## 5.1 二维卷积层"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "TGdFNCpTqZ6z",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "# !pip install d2lzh mxnet"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "CFdR88U9qpOw",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "from mxnet import autograd, nd \n",
        "from mxnet.gluon import nn\n",
        "\n",
        "def corr2d(X, K):\n",
        "    h, w = K.shape\n",
        "    print(h, w)\n",
        "    Y = nd.zeros((X.shape[0] - h + 1, X.shape[1] - w + 1))\n",
        "    for i in range(Y.shape[0]):\n",
        "        for j in range(Y.shape[1]):\n",
        "            Y[i, j] = (X[i: i + h, j: j + w] * K).sum()\n",
        "    return Y"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "WUz7_TwkrsCm",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 101
        },
        "outputId": "432291cd-d150-455c-a9e0-934a7bb80042"
      },
      "source": [
        "X = nd.array([[0, 1, 2], [3, 4, 5], [6, 7, 8]])\n",
        "K = nd.array([[0, 1], [2, 3]])\n",
        "corr2d(X, K)"
      ],
      "execution_count": 4,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "2 2\n"
          ],
          "name": "stdout"
        },
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "\n",
              "[[19. 25.]\n",
              " [37. 43.]]\n",
              "<NDArray 2x2 @cpu(0)>"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 4
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "Ub0dFbdhs3u9",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "class Conv2D(nn.Block):\n",
        "    def __init__(self, kernel_size, **kwargs):\n",
        "        super(Conv2D, self).__init__(**kwargs)\n",
        "        self.weight = self.params.get('weight', shape=kernel_size)\n",
        "        self.bias = self.params.get('bias', shape=(1, ))\n",
        "\n",
        "    def forward(self, x):\n",
        "        return corr2d(x, self.weight.data()) + self.bias.data()"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "wAHWQwZ8vT2e",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 151
        },
        "outputId": "1a0ae95c-1d89-4aed-8cec-0df6b489aa68"
      },
      "source": [
        "X = nd.ones((6, 8))\n",
        "X[:, 2:6] = 0 \n",
        "X"
      ],
      "execution_count": 6,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "\n",
              "[[1. 1. 0. 0. 0. 0. 1. 1.]\n",
              " [1. 1. 0. 0. 0. 0. 1. 1.]\n",
              " [1. 1. 0. 0. 0. 0. 1. 1.]\n",
              " [1. 1. 0. 0. 0. 0. 1. 1.]\n",
              " [1. 1. 0. 0. 0. 0. 1. 1.]\n",
              " [1. 1. 0. 0. 0. 0. 1. 1.]]\n",
              "<NDArray 6x8 @cpu(0)>"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 6
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "Uqm1raulxqSZ",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "K = nd.array([[1, -1]])"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "ZVo3pA1Mxy0C",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 168
        },
        "outputId": "335add4c-0c1b-46a4-b848-27ac6000bd9f"
      },
      "source": [
        "Y = corr2d(X, K)\n",
        "Y"
      ],
      "execution_count": 8,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "1 2\n"
          ],
          "name": "stdout"
        },
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "\n",
              "[[ 0.  1.  0.  0.  0. -1.  0.]\n",
              " [ 0.  1.  0.  0.  0. -1.  0.]\n",
              " [ 0.  1.  0.  0.  0. -1.  0.]\n",
              " [ 0.  1.  0.  0.  0. -1.  0.]\n",
              " [ 0.  1.  0.  0.  0. -1.  0.]\n",
              " [ 0.  1.  0.  0.  0. -1.  0.]]\n",
              "<NDArray 6x7 @cpu(0)>"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 8
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "vz3xITt3x2Wp",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 101
        },
        "outputId": "af344107-a78a-42bd-ec59-955994a8e6f7"
      },
      "source": [
        "conv2d = nn.Conv2D(1, kernel_size=(1, 2))\n",
        "conv2d.initialize()\n",
        "\n",
        "X = X.reshape((1, 1, 6, 8))\n",
        "Y = Y.reshape((1, 1, 6, 7))\n",
        "\n",
        "for i in range(10):\n",
        "    with autograd.record():\n",
        "        Y_hat = conv2d(X)\n",
        "        l = (Y_hat - Y) ** 2 \n",
        "    l.backward()\n",
        "    conv2d.weight.data()[:] -= 3e-2 * conv2d.weight.grad()\n",
        "    if (i + 1) % 2 == 0:\n",
        "        print('batch %d, loss %.3f' % (i + 1, l.sum().asscalar()))"
      ],
      "execution_count": 9,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "batch 2, loss 4.949\n",
            "batch 4, loss 0.831\n",
            "batch 6, loss 0.140\n",
            "batch 8, loss 0.024\n",
            "batch 10, loss 0.004\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "eFyqLMAVtCJx",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 67
        },
        "outputId": "34c8c0c1-e3c3-459f-d84a-d4a270fa04a3"
      },
      "source": [
        "conv2d.weight.data().reshape((1, 2))"
      ],
      "execution_count": 10,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "\n",
              "[[ 0.9895    -0.9873705]]\n",
              "<NDArray 1x2 @cpu(0)>"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 10
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "fHWX3BjftJPa",
        "colab_type": "text"
      },
      "source": [
        "## 5.2 填充和步幅"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "u_lD4SMoC8YR",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 34
        },
        "outputId": "294d0dde-985a-4d0b-fd7e-09e20ce2b26b"
      },
      "source": [
        "from mxnet import nd \n",
        "from mxnet.gluon import nn \n",
        "\n",
        "def comp_conv2d(conv2d, X):\n",
        "    conv2d.initialize()\n",
        "    X = X.reshape((1, 1) + X.shape)\n",
        "    Y = conv2d(X)\n",
        "    return Y.reshape(Y.shape[2:])\n",
        "\n",
        "conv2d = nn.Conv2D(1, kernel_size=3, padding=1)\n",
        "X = nd.random.uniform(shape=(8, 8))\n",
        "comp_conv2d(conv2d, X).shape"
      ],
      "execution_count": 12,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "(8, 8)"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 12
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "LlLSizV6D273",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 34
        },
        "outputId": "f9ae887f-5243-48b0-d548-5a34acf6868e"
      },
      "source": [
        "conv2d = nn.Conv2D(1, kernel_size=(5, 3), padding=(2, 1))\n",
        "comp_conv2d(conv2d, X).shape"
      ],
      "execution_count": 13,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "(8, 8)"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 13
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "0EjtnectECiM",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 34
        },
        "outputId": "ff62577e-a04e-490b-8db9-c847a6e50d46"
      },
      "source": [
        "conv2d = nn.Conv2D(1, kernel_size=3, padding=1, strides=2)\n",
        "comp_conv2d(conv2d, X).shape"
      ],
      "execution_count": 14,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "(4, 4)"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 14
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "x787UJPcETgA",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 34
        },
        "outputId": "c853b13c-3d37-44a2-8910-1b027e63b5b7"
      },
      "source": [
        "conv2d = nn.Conv2D(1, kernel_size=(3, 5), padding=(0, 1), strides=(3, 4))\n",
        "comp_conv2d(conv2d, X).shape"
      ],
      "execution_count": 15,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "(2, 2)"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 15
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "KzwloKLTGcdy",
        "colab_type": "text"
      },
      "source": [
        "## 5.3 多输入通道和多输出通道"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "43xYUkwHGkJe",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "import d2lzh as d2l \n",
        "from mxnet import nd \n",
        "\n",
        "def corr2d_multi_in(X, K):\n",
        "    return nd.add_n(*[d2l.corr2d(x, k) for x, k in zip(X, K)])"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "c8O1u7wuHPnC",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 84
        },
        "outputId": "8e534e30-c394-4602-dc80-dc1b3e55f575"
      },
      "source": [
        "X = nd.array([[[0, 1, 2], [3, 4, 5], [6, 7, 8]], \n",
        "        [[1, 2, 3], [4, 5, 6], [7, 8, 9]]])\n",
        "K = nd.array([[[0, 1], [2, 3]], [[1, 2], [3, 4]]])\n",
        "\n",
        "corr2d_multi_in(X, K)"
      ],
      "execution_count": 18,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "\n",
              "[[ 56.  72.]\n",
              " [104. 120.]]\n",
              "<NDArray 2x2 @cpu(0)>"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 18
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "9KrRIPVFH5uF",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "def corr2d_multi_in_out(X, K):\n",
        "    return nd.stack(*[corr2d_multi_in(X, k) for k in K])"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "Okz29MH2JMjC",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 34
        },
        "outputId": "d795a2d4-690f-42a8-de6e-e043072f744d"
      },
      "source": [
        "K = nd.stack(K, K + 1, K + 2)\n",
        "K.shape"
      ],
      "execution_count": 20,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "(3, 2, 2, 2)"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 20
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "CVLOkXp6JRSF",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 185
        },
        "outputId": "abd68b76-6f57-4fa4-aef4-fbf63edf38e6"
      },
      "source": [
        "corr2d_multi_in_out(X, K)"
      ],
      "execution_count": 21,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "\n",
              "[[[ 56.  72.]\n",
              "  [104. 120.]]\n",
              "\n",
              " [[ 76. 100.]\n",
              "  [148. 172.]]\n",
              "\n",
              " [[ 96. 128.]\n",
              "  [192. 224.]]]\n",
              "<NDArray 3x2x2 @cpu(0)>"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 21
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "jyUY5UqgJeDK",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "def corr2d_multi_in_out_1x1(X, K):\n",
        "    c_i, h, w = X.shape \n",
        "    c_o = K.shape[0]\n",
        "    X = X.reshape((c_i, h * w))\n",
        "    K = K.reshape((c_o, c_i))\n",
        "    Y = nd.dot(K, X)\n",
        "    return Y.reshape((c_o, h, w))"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "8YcRPOYZJ9C5",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 34
        },
        "outputId": "15f12da4-46a1-43f5-96a5-b34d0ae8797f"
      },
      "source": [
        "X = nd.random.uniform(shape=(3, 3, 3))\n",
        "K = nd.random.uniform(shape=(2, 3, 1, 1))\n",
        "Y1 = corr2d_multi_in_out_1x1(X, K)\n",
        "Y2 = corr2d_multi_in_out(X, K)\n",
        "\n",
        "(Y1 - Y2).norm().asscalar() < 1e-6"
      ],
      "execution_count": 23,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "True"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 23
        }
      ]
    }
  ]
}